﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcControlToolkit
{
    public static class FilteredTextBoxExtensions
    {
        private static readonly int DEFAULT_INTERVAL = 250;
        private static readonly FilterModes DEFAULT_MODE = FilterModes.ValidChars;

        /// <summary>
        /// Creates a FilteredTextBox extender allowing characters specified by the type flag
        /// </summary>
        /// <param name="elementId">The ID of the text box for this extender to operate on</param>
        /// <param name="type">A the type of filter to apply, as a OR-ed combination of Numbers, LowercaseLetters, UppercaseLetters, and Custom</param>
        public static string FilteredTextBox(this AjaxHelper helper, string elementId, FilterTypes type)
        {
            return helper.FilteredTextBox(elementId, new { FilterType = type });
        }

        /// <summary>
        /// Creates a FilteredTextBox extender allowing only the specified characters 
        /// characters allowed by the type flag
        /// </summary>
        /// <param name="elementId">The ID of the text box for this extender to operate on</param>
        /// <param name="type">A the type of filter to apply, as a OR-ed combination of Numbers, LowercaseLetters, UppercaseLetters, and Custom</param>
        /// <param name="validChars">A string consisting of all characters considered valid for the text field</param>
        public static string FilteredTextBox(this AjaxHelper helper, string elementId, FilterTypes type, string validChars)
        {
            return helper.FilteredTextBox(elementId, type, FilterModes = FilterModes.ValidChars, validChars, "", DEFAULT_INTERVAL);            
        }

        /// <summary>
        /// Creates a FilteredTextBox extender allowing anything but the specified characters
        /// </summary>
        /// <param name="elementId">The ID of the text box for this extender to operate on</param>
        /// <param name="invalidChars">A string consisting of all characters considered invalid for the text field</param>
        public static string FilteredTextBox(this AjaxHelper helper, string elementId, string invalidChars)
        {
            return helper.FilteredTextBox(elementId, FilterTypes.Custom, FilterModes.InvalidChars, "", invalidChars, DEFAULT_INTERVAL);
        }

        /// <summary>
        /// Creates a FilteredTextBox extender with the specified properties
        /// </summary>        
        /// <param name="elementId">The ID of the text box for this extender to operate on</param>
        /// <param name="filterType">A the type of filter to apply, as a OR-ed combination of Numbers, LowercaseLetters, UppercaseLetters, and Custom. If Custom is specified, the ValidChars field will be used in addition to other settings such as Numbers</param>
        /// <param name="filterMode">A the filter mode to apply, either ValidChars (default) or InvalidChars. If set to InvalidChars, FilterType must be set to Custom; if set to ValidChars, FilterType must contain Custom</param>
        /// <param name="validChars">A string consisting of all characters considered valid for the text field, if "Custom" is specified as the filter type. Otherwise this parameter is ignored</param>
        /// <param name="invalidChars">A string consisting of all characters considered invalid for the text field, if "Custom" is specified as the filter type and "InvalidChars" as the filter mode. Otherwise this parameter is ignored</param>
        /// <param name="filterInterval">An integer containing the interval (in milliseconds) in which the field's contents are filtered, defaults to 250</param>
        public static string FilteredTextBox(this AjaxHelper helper, string elementId, FilterTypes filterType, FilterModes filterMode, string validChars, string invalidChars, int filterInterval)
        {
            RouteValueDictionary props = new RouteValueDictionary();
            props.Add("FilterType", filterType);
            props.AddIfNotEqual("FilterMode", DEFAULT_MODE);

            if (filterType & FilterTypes.Custom == FilterTypes.Custom)
                props.AddIfNotDefault("ValidChars", validChars);

            if(filterType & FilterTypes.Custom == FilterTypes.Custom)
            {
                if (filterMode & FilterModes.InvalidChars == FilterModes.InvalidChars)
                    props.AddIfNotDefault("InvalidChars", invalidChars);
            }

            props.AddIfNotEqual("FilterInterval", filterInterval, DEFAULT_INTERVAL);

            return helper.FilteredTextBox(elementId, props);
        }
        
        /// <summary>
        /// Creates a FilteredTextBox extender with the specified properties
        /// </summary>
        /// <param name="elementId">The ID of the text box for this extender to operate on</param>
        /// <param name="properties">An object containing the properties to be set</param>
        public static string FilteredTextBox(this AjaxHelper helper, string elementId, object properties)
        {
            var sb = new StringBuilder();

            // Add Microsoft Ajax library   
            sb.Append(helper.MicrosoftAjaxInclude());

            // Add toolkit scripts   
            sb.Append(helper.ToolkitInclude(
                    "AjaxControlToolkit.ExtenderBase.BaseScripts.js",
                    "AjaxControlToolkit.Common.Common.js",
                    "AjaxControlToolkit.FilteredTextBox.FilteredTextBoxBehavior.js"
                ));

            // Perform $create               
            sb.AppendLine(helper.Create("AjaxControlToolkit.FilteredTextBoxBehavior", properties, elementId));

            return sb.ToString();
        }
    }

    #region [Enumerations]

    [Flags]
    public enum FilterModes
    {
        ValidChars = 0x1,
        InvalidChars = 0x2
    }

    [Flags]
    public enum FilterTypes
    {
        Custom = 0x1,
        Numbers = 0x2,
        UppercaseLetters = 0x4,
        LowercaseLetters = 0x8
    }

    #endregion
}
